<?php 
namespace lib;
class XFCaptcha{
    private $captchakey;
    private $CaptchaCode;
    
    public function __construct($CaptchaCode = 'ALL') {
        $this->captchakey  = 'XFcaptcha1745';
        $this->CaptchaCode = $CaptchaCode;
    }
    
    public function generateCaptcha($len = '4') {
        // 创建画布
        $width = 103;
        $height = 40;
        $image = imagecreatetruecolor($width, $height);
    
        // 设置背景颜色
        list($r, $g, $b) = $this->colorRandom();
        $backgroundColor = imagecolorallocate($image, $r, $g, $b);
        imagefill($image, 0, 0, $backgroundColor);
    
        // 生成随机字符
        $captchaCode = $this->generateCaptchaCode($len);
        $fontSize = 16; // 设置字体大小
        $fontPath = SYSTEM_ROOT.'assets/ttf/mj1.ttf'; // 指定字体文件路径
        for ($i = 0; $i < strlen($captchaCode); $i++) {
            $randomChar = $captchaCode[$i];
    
            // 设置字体颜色
            list($r, $g, $b) = $this->randomColor(0,200);
    
            $fontColor = imagecolorallocate($image, $r, $g, $b);
           
            
            // 将字符写入画布
            $x = 5 + ($i * 24); // 根据画布宽度调整X轴位置
            $y = $this->randomNum(5, 20); // 随机Y轴位置
            $y += $fontSize; // 调整Y轴位置以适应字体大小
            // imagestring($image, 5, $x, $y, $randomChar, $fontColor);
            imagettftext($image, $fontSize, 0, $x, $y, $fontColor, $fontPath, $randomChar);
        }
        $token = aes256auth($captchaCode,$this->captchakey);
        // 将验证码存入SESSION
        $_SESSION['XFcaptcha'] = $token;
    
        // 绘制干扰线
        for ($i = 0; $i < 6; $i++) {
            list($r, $g, $b) = $this->randomColor(0,200);
            $lineColor = imagecolorallocate($image, $r, $g, $b);
            imageline($image, mt_rand(0, $width), mt_rand(0, $height), mt_rand(0, $width), mt_rand(0, $height), $lineColor);
        }
    
        // 绘制干扰点
        for ($i = 0; $i < 50; $i++) { // 根据画布大小调整点的数量
            list($r, $g, $b) = $this->randomColor(0,200);
            $pointColor = imagecolorallocate($image, $r, $g, $b);
            imagesetpixel($image, mt_rand(0, $width), mt_rand(0, $height), $pointColor);
        }
    
        // 输出图片
        header('Content-Type: image/png');
        imagepng($image);
    
        // 销毁图像资源
        imagedestroy($image);
    }
    
    public function XYcaptcha($code){
        // return $_SESSION['XFcaptcha'];
        $captchacode = $this->aes256auth($_SESSION['XFcaptcha'],$this->captchakey,'DECODE');
        return ($captchacode == $code);
    }
    private function colorRandom(){
        $r = $this->randomNum(200, 255);
        $g = $this->randomNum(200, 255);
        $b = $this->randomNum(200, 255);
        return [$r, $g, $b];
    }
    private function randomNum($min, $max) {
        return mt_rand($min, $max);
    }
    private function randomColor($min, $max) {
        $r = $this->randomNum($min, $max);
        $g = $this->randomNum($min, $max);
        $b = $this->randomNum($min, $max);
        return [$r, $g, $b];
    }
    
    // 生成验证码字符池
    private function generateCaptchaCode($length = 4) {
        $is_abc = $is_numer = 0;
        $password = $tmp ='';
        
        switch($this->CaptchaCode){
            case 'ALL':
                $chars='ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
            break;
            case 'CHAR':
                $chars='ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz';
            break;
            case 'NUMBER':
                $chars='0123456789';
            break;
            default :
                $chars='ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnopqrstuvwxyz23456789';
            break;
        }
        mt_srand((double)microtime()*1000000*getmypid());
        while(strlen($password)<$length){
            $tmp =substr($chars,(mt_rand()%strlen($chars)),1);
            if(($is_numer <> 1 && is_numeric($tmp) && $tmp > 0 )|| $this->CaptchaCode == 'CHAR'){
                $is_numer = 1;
            }
            if(($is_abc <> 1 && preg_match('/[a-zA-Z]/',$tmp)) || $this->CaptchaCode == 'NUMBER'){
                $is_abc = 1;
            }
            $password.= $tmp;
        }
        if($is_numer <> 1 || $is_abc <> 1 || empty($password) ){
            $password = randpw($length,$this->CaptchaCode);
        }
        return $password;
    }
    private function aes256auth($data,$key,$operation='ENCODE'){//aes 256 加密
        if($operation == 'DECODE'){//解密
            $data = base64_decode($data);
             $decodedData = base64_decode($data);//两次 b64解密
              $iv = substr($decodedData, 0, 16);//取解密后的前16位作为 iv
              $encryptedData = substr($decodedData, 16);//取16位后面的作为解密内容
              $openssl=openssl_decrypt($encryptedData, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);//进行解密
              if($openssl === false){
                  return false;
              }
              return base64_decode($openssl);//解密成功 在进行一次 b64解密并返回解密后的字符
        }else{//加密
            $data = base64_encode($data);//对原始数据 b64 加密一次
            $iv = random_bytes(16);//随机生成 16位作为 iv加密字符
            $encryptedData = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);//进行加密
            $encodedData = base64_encode($iv . $encryptedData);//拼接数据  并 b64加密一次
            return base64_encode($encodedData);//在加密一次
        }
}
    
}
?>